package com.aos.erp.schools.rest.message;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aos.erp.common.bean.PageBean;
import com.aos.erp.common.bean.ResultEntity;
import com.aos.erp.common.exception.BizException;
import com.aos.erp.common.utils.StringUtils;
import com.aos.erp.schools.model.gatherschool.entity.GatherSchool;
import com.aos.erp.schools.model.student.StudentNews;
import com.aos.erp.schools.model.student.ro.news.NewsRo;
import com.aos.erp.schools.model.student.vo.news.NewsVo;
import com.aos.erp.schools.model.sys.dto.UserDto;
import com.aos.erp.schools.remote.MessageService;
import com.aos.erp.schools.remote.model.MTPushTypeParam;
import com.aos.erp.schools.remote.model.MessageTemplateInfo;
import com.aos.erp.schools.remote.model.dto.MessageRecordItemDTO;
import com.aos.erp.schools.remote.model.dto.MessageTemplateDTO;
import com.aos.erp.schools.remote.model.dto.MessageTemplateItemDTO;
import com.aos.erp.schools.remote.model.vo.MRConditionVo;
import com.aos.erp.schools.remote.model.vo.MTConditionVo;
import com.aos.erp.schools.remote.model.vo.PushMessageVo;
import com.aos.erp.schools.remote.model.vo.PushStudentVo;
import com.aos.erp.schools.service.student.StudentNewsService;
import com.aos.erp.schools.service.student.StudentService;
import com.aos.erp.schools.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Api(tags = {"UI接口：消息接口"})
@RestController
@RequestMapping("/api/message")
public class RestMessageController {

    @Resource
    private MessageService messageService;

    @Resource
    private StudentService studentService;

    @Resource
    private StudentNewsService studentNewsService;

    @ApiOperation(value = "分页查询消息模板")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageIndex", value = "当前页", required = true, dataType = "Integer", defaultValue = "1", paramType = "Query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", required = true, dataType = "Integer", defaultValue = "20", paramType = "Query"),
            @ApiImplicitParam(name = "mtCode", value = "模板编号", dataType = "String", paramType = "Query"),
            @ApiImplicitParam(name = "mtTitle", value = "模板标题", dataType = "String", paramType = "Query")
    })
    @GetMapping("/template/list")
    public ResultEntity<PageBean<MessageTemplateItemDTO>> listTemplate(MTConditionVo params, String currentUserId) throws Exception {
        long driverSchoolId = 480;
        String dsId = UserUtil.getUserSchoolId(currentUserId);
        if(StringUtils.isNotEmpty(dsId)) {
            driverSchoolId = Long.parseLong(dsId);
        } else {
            throw new BizException("您无权查看消息模板");
        }
        params.setDriverSchoolId(driverSchoolId);
        return ResultEntity.success(messageService.queryTemplateForPage(params));
    }

    @GetMapping("/template/listAll")
    @ApiOperation(value = "查询所有消息模板")
    public ResultEntity<List<MessageTemplateInfo>> listAllTemplate(String currentUserId) throws Exception {
        long driverSchoolId = 480;
        String dsId = UserUtil.getUserSchoolId(currentUserId);
        if(StringUtils.isNotEmpty(dsId)) {
            driverSchoolId = Long.parseLong(dsId);
        } else {
            throw new BizException("您无权获取所有消息模板");
        }
        return ResultEntity.success(messageService.queryAllTemplate(driverSchoolId));
    }

    @ApiOperation(value = "查看模板详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dataId", value = "模板ID", required = true, dataType = "Long", paramType = "Query")
    })
    @GetMapping("/template/detail")
    public ResultEntity<MessageTemplateDTO> detailTemplate(Long dataId){

        // 获取消息模板
        MessageTemplateDTO messageTemplateDTO = messageService.getMessageTemplateDetail(dataId);
        return ResultEntity.success(messageTemplateDTO);
    }

    @ApiOperation(value = "查询推送学员列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageIndex", value = "当前页", required = true, dataType = "Integer", defaultValue = "1", paramType = "Query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", required = true, dataType = "Integer", defaultValue = "20", paramType = "Query"),
            @ApiImplicitParam(name = "searchKey", value = "查询关键字（学员姓名、证件号码）", dataType = "String", paramType = "Query"),
            @ApiImplicitParam(name = "examTime", value = "考试日期", dataType = "String", paramType = "Query"),
            @ApiImplicitParam(name = "carId", value = "准驾车型", dataType = "Integer", paramType = "Query"),
            @ApiImplicitParam(name = "phase", value = "学员阶段(1：科目一；2：科目二；3：科目三；4：科目四)", dataType = "Integer", paramType = "Query"),
            @ApiImplicitParam(name = "pushType", value = "推送类型（1：约考结果推送；2：考试结果推送）", dataType = "Integer", paramType = "Query")
    })
    @GetMapping("/student/waitSendList")
    public ResultEntity<PageBean<NewsVo>> waitSendStudentList(NewsRo params, String currentUserId) throws Exception {
        long driverSchoolId = 480;
        String dsId = UserUtil.getUserSchoolId(currentUserId);
        if(StringUtils.isNotEmpty(dsId)) {
            driverSchoolId = Long.parseLong(dsId);
        } else {
            throw new BizException("您无权获取学员信息");
        }
        params.setDriverSchoolId(driverSchoolId);

        List<NewsVo> studentList = pageQueryStudentList(params);

        PageBean<NewsVo> pageBean = new PageBean<>();
        pageBean.setRecords(studentList);
        pageBean.setTotal(studentList.size());
        pageBean.setSize(studentList.size());
        pageBean.setCurrent(1);

        return ResultEntity.success(pageBean);
    }

    /**
     * 获取要推送消息的学员列表
     * @param params
     * @return
     */
    private List<NewsVo> pageQueryStudentList(NewsRo params) {
        List<NewsVo> studentList = new ArrayList<>();
        PageBean<NewsVo> pageBean = studentService.selectStudentByIdNews(params);
        studentList.addAll(pageBean.getRecords());

        // 检测是否还有数据
        if(pageBean.hasNext()) {
            params.setPageIndex(params.getPageIndex() + 1);
            List<NewsVo> nextPageList = pageQueryStudentList(params);
            studentList.addAll(nextPageList);
        }
        return studentList;
    }


    @ApiOperation(value = "删除消息记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "记录ID：id1,id2,id3", required = true, dataType = "Long", paramType = "Query")
    })
    @GetMapping("/record/delete")
    public ResultEntity deleteRecord(String ids) throws Exception{
        return messageService.deleteRecord(ids);
    }

    @ApiOperation(value = "查询推送记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageIndex", value = "当前页", required = true, dataType = "Integer", defaultValue = "1", paramType = "Query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", required = true, dataType = "Integer", defaultValue = "20", paramType = "Query"),
            @ApiImplicitParam(name = "mrContent", value = "推送内容", dataType = "String", paramType = "Query"),
            @ApiImplicitParam(name = "pushType", value = "推送方式(app:APP；wx_public:微信公众号；wx_applet:微信小程序；)", dataType = "PushType", paramType = "Query"),
            @ApiImplicitParam(name = "pushStatus", value = "推送状态：push_no为未发送；push_yes为已发送；push_stop为暂停发送", dataType = "PushStatus", paramType = "Query"),
            @ApiImplicitParam(name = "fromTime", value = "发送开始时间", dataType = "String", paramType = "Query"),
            @ApiImplicitParam(name = "toTime", value = "发送截止时间", dataType = "String", paramType = "Query")
//            @ApiImplicitParam(name = "driverSchoolId", value = "驾校ID", dataType = "Long", paramType = "Query")
    })
    @GetMapping("/record/list")
    public ResultEntity<PageBean<MessageRecordItemDTO>> listTemplate(MRConditionVo params, String currentUserId) throws Exception {
        long driverSchoolId = 480;
        String dsId = UserUtil.getUserSchoolId(currentUserId);
        if(StringUtils.isNotEmpty(dsId)) {
            driverSchoolId = Long.parseLong(dsId);
        } else {
            throw new BizException("您无权查看消息推送记录");
        }
        params.setDriverSchoolId(driverSchoolId);
        return ResultEntity.success(messageService.queryRecordForPage(params));
    }

    @ApiOperation(value = "推送消息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mtId", value = "消息模板ID", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "studentList", value = "推送学员列表[{studentId:学员id,idNo:'证件号码',studentName:'学员名字',studentPhone:'学员电话',carName:'准驾车型',coachName:'教练名字',coachPhone:'教练电话',examSubject:'考试科目',examAddress:'考试地点',examTime:'考试时间',examResult:'考试结果'}]", required = true, dataType = "List"),
            @ApiImplicitParam(name = "pushMessageForApp", value = "APP推送消息内容", dataType = "String"),
            @ApiImplicitParam(name = "pushMessageForPublic", value = "微信公众号推送消息内容", dataType = "String"),
            @ApiImplicitParam(name = "pushMessageForApplet", value = "微信小程序推送消息内容", dataType = "String"),
            @ApiImplicitParam(name = "pushMessageForSms", value = "短信推送消息内容", dataType = "String"),
            @ApiImplicitParam(name = "formId", value = "微信小程序需要，表单提交场景下，为 submit 事件带上的 formId", dataType = "String"),
            @ApiImplicitParam(name = "phase", value = "学员阶段(1：科目一；2：科目二；3：科目三；4：科目四)", dataType = "Integer", paramType = "Query"),
            @ApiImplicitParam(name = "pushType", value = "推送类型（1：约考结果推送；2：考试结果推送）", dataType = "Integer", paramType = "Query")
    })
    @PostMapping("/pushMessage")
    public ResultEntity pushMessage(@RequestBody PushMessageVo params, String currentUserId) throws Exception {

        checkPushData(params);
        // 获取驾校信息
        GatherSchool gatherSchool = UserUtil.getUserSchool(currentUserId);
        params.setDsId(gatherSchool.getId());
        params.setDsName(gatherSchool.getName());
        // 获取当前用户信息
        UserDto userDto = UserUtil.getUserInfo(currentUserId);
        params.setSenderName(userDto.getName());

//        // 获取驾校信息
//        params.setDsId(480);
//        params.setDsName("上海总校");
//        // 获取当前用户信息
//        params.setSenderName("张老师");

        // 根据APP需要，组装APP业务参数
        params.setBizData("");

        // 根据模板Id获取模板详情（需要使用模板参数）
        MessageTemplateDTO messageTemplateDTO = messageService.getMessageTemplateDetail(params.getMtId());

        // 组装推送消息和推送参数
        for (NewsVo newsVo : params.getStudentList()) {
            params.getPushStudentList().add(getPushStudent(params, newsVo, messageTemplateDTO));
        }
        ResultEntity<PushStudentVo> pushResult =  messageService.pushMessage(params);
        if(pushResult.getCode() == ResultEntity.CODE_SUCCESS) {
            for (NewsVo newsVo : params.getStudentList()) {
                StudentNews studentNews = new StudentNews();
                studentNews.setDriverId(gatherSchool.getId());
                studentNews.setPhase(params.getPhase());
                studentNews.setPushType(params.getPushType());
                studentNews.setUserId(userDto.getId());
                studentNews.setStudentId(newsVo.getStudentId());
                studentNews.setNewState(1); // 发送中
                studentNewsService.saveBean(studentNews);
            }
            return ResultEntity.success();
        } else {
            return ResultEntity.failed(pushResult.getMessage(), pushResult.getCode());
        }
    }

    /**
     * 获取学员推送信息
     * @param params
     * @param newsVo
     * @param messageTemplateDTO
     * @return
     */
    private PushStudentVo getPushStudent(PushMessageVo params, NewsVo newsVo, MessageTemplateDTO messageTemplateDTO) {
        PushStudentVo studentVo = new PushStudentVo();

        // 学员基本信息
        BeanUtils.copyProperties(newsVo, studentVo);

        // 处理APP推送消息
        JSONArray msgParamForApp = getMsgParam(newsVo, messageTemplateDTO.getAppPushParamList());
        studentVo.setMsgParamsForApp(msgParamForApp.toJSONString());
        studentVo.setPushMessageForApp(analysisPushMessage(params.getPushMessageForApp(), msgParamForApp));

        // 处理微信公众号推送消息
        JSONArray msgParamForPublic = getMsgParam(newsVo, messageTemplateDTO.getPublicPushParamList());
        studentVo.setMsgParamsForPublic(msgParamForPublic.toJSONString());
        studentVo.setPushMessageForPublic(analysisPushMessage(params.getPushMessageForPublic(), msgParamForPublic));

        // 处理小程序推送消息
        JSONArray msgParamForApplet = getMsgParam(newsVo, messageTemplateDTO.getAppletPushParamList());
        studentVo.setMsgParamsForApplet(msgParamForApplet.toJSONString());
        studentVo.setPushMessageForApplet(analysisPushMessage(params.getPushMessageForApplet(), msgParamForApplet));

        // 处理短信推送消息
        JSONArray msgParamForSms = getMsgParam(newsVo, messageTemplateDTO.getSmsPushParamList());
        studentVo.setMsgParamsForSms(msgParamForSms.toJSONString());
        studentVo.setPushMessageForSms(analysisPushMessage(params.getPushMessageForSms(), msgParamForSms));
        return studentVo;
    }

    /**
     * 解析推送文本，替换参数
     * @param mtContent
     * @param msgParamArray
     * @return
     */
    private String analysisPushMessage(String mtContent, JSONArray msgParamArray) {
        for (int i = 0; i < msgParamArray.size(); i++) {
            JSONObject paramItem = msgParamArray.getJSONObject(i);
            mtContent = mtContent.replace(paramItem.getString("paramKey"), paramItem.getString("paramValue"));
        }
        return mtContent;
    }

    /**
     * 获取消息参数
     * @param pushParamList
     */
    private JSONArray getMsgParam(NewsVo newsVo, List<MTPushTypeParam> pushParamList) {

        JSONArray msgParamArray = new JSONArray();
        for (MTPushTypeParam pushTypeParam : pushParamList) {
            String paramValue = "";
            if("{studentName}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getStudentName();
            } else if("{studentPhone}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getStudentPhone();
            } else if("{coachName}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getCoachName();
            } else if("{coachPhone}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getCoachPhone();
            } else if("{examCourse}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getExamSubject();
            } else if("{examSite}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getExamAddress();
            } else if("{examTime}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getExamTime();
            } else if("{examResult}".equals(pushTypeParam.getMtpItem())) {
                paramValue = newsVo.getExamResult();
            } else {
                paramValue = "";
            }
            if(paramValue != "") {
                JSONObject paramItem = new JSONObject();
                paramItem.put("paramKey", pushTypeParam.getMtpItem());
                paramItem.put("paramValue", paramValue);
                msgParamArray.add(paramItem);
            }
        }

        return msgParamArray;
    }

    /**
     * 校验推送数据
     * @param params
     * @throws Exception
     */
    private void checkPushData(PushMessageVo params) throws Exception {
        if(params.getMtId() == 0) {
            throw new BizException("模板Id不能为空");
        }

        if(params.getStudentList().size() == 0) {
            throw new BizException("学员未选择");
        }

        if(!StringUtils.isNotEmpty(params.getPushMessageForApp())
                && !StringUtils.isNotEmpty(params.getPushMessageForPublic())
                && !StringUtils.isNotEmpty(params.getPushMessageForApplet())
                && !StringUtils.isNotEmpty(params.getPushMessageForSms())) {
            throw new BizException("推送消息不能为空");
        }

//        Pattern pattern = Pattern.compile("\\{[\\S]*\\}");
//        Matcher matcherForApp = pattern.matcher(params.getPushMessageForApp());
//        Matcher matcherForPublic = pattern.matcher(params.getPushMessageForPublic());
//        Matcher matcherForApplet = pattern.matcher(params.getPushMessageForApplet());
//        Matcher matcherForSms = pattern.matcher(params.getPushMessageForSms());
//        if(matcherForApp.matches() || matcherForPublic.matches() || matcherForApplet.matches() || matcherForSms.matches()) {
//            throw new BizException("推送消息有未被替换的参数");
//        }
    }
}
